#include "m1api.h"

U32 gWalletM1[3];
U32 MonStart;
U08	M1Key[16][8];
U08 sM1Key[8];
U08 gM1CardSN[8];
U08 gM1_Publish_00[16];	
U08 gM1_ComBuf16Byte[16];				//钱包加/减成功后，暂存公共区数据，此时进程标识已经为开始中
static U08 MAINKEY[8] = {0x01,0xF6,0x98,0x50,0xE4,0x8A,0x4C,0x63};//保定M1卡主密钥

U08 PsamStat;

void CurCalc_DataCpy( U08 *outbuf, U08 *inbuf, U32 insize )			//数据复制
{
	memcpy( outbuf, inbuf, insize);
}
void CurCalc_DataSet( U08 *outbuf, U08 indata, U32 insize )			//数据设置
{
	memset(outbuf, indata, insize);
}
U32  CurCalc_DataCmp( U08 *inbuf1, U08 *inbuf2, U32 insize )		//数据比较
{
	return memcmp( inbuf1, inbuf2, insize );
}

//数据校验
static U08	CheckXOR( U08 *pdata )
{
	U08 i,check;

	check = pdata[0];

	for( i = 1; i < 16; i++ )
	{ check ^= pdata[i]; }
	return check;
}

//钱包校验，0校验通过
static U32 CheckWallet( U08 *data )
{
	S32 sm;
	
	if( memcmp( data, data+8, 4 ) == 0 )			//正
	{
		if( ( data[0] ^ data[4] ) == 0xFF )
		if( ( data[1] ^ data[5] ) == 0xFF )
		if( ( data[2] ^ data[6] ) == 0xFF )
		if( ( data[3] ^ data[7] ) == 0xFF )
		{ 
			sm = ( 	( data[0] <<  0 ) |						//卡内余额 
	         		( data[1] <<  8 ) | 
			 		( data[2] << 16 ) | 
			 		( data[3] << 24 ) );
			if( sm < 0 )
			{ return 1; }
			return 0; 
		}	
	}
	return 1;
}

U32 M1Card_Hook_GetKey(	U08 *CityCode, 		 
						U08 *Snr, 
						U08 *Csn, 
						U08 *MacCode, 
						U08 *CityCiph, 
						U08 *Sectors, 
						U08 nSector,
						U08 *kbuf )
{
	return 1;
}

/*
**************************************************************************************************************
*
* 函数原型：APP_M1Card_Hook_GetKey
*
* 函数功能：获取Mifare卡扇区密钥
*
* 函数输入：CityCode	2字节城市代码
*			Snr  		4字节卡片序列号
*			Csn 		2字节发行流水号的后两字节
*			MacCode 	4字节验证码
*			CityCiph 	8字节城市代码散列值 
*			Sectors 	扇区代码 
*			nSector 	扇区数量
*
* 函数输出：kbuf		KEY存储缓冲区，长度＝6*nSector
*
* 函数返回：0			成功
*			其它		失败
*   
**************************************************************************************************************
*/
U32 APP_M1Card_Hook_GetKey(U08 *CityCode, 		 
	                       U08 *Snr, 
	                       U08 *Csn, 
	                       U08 *MacCode, 
	                       U08 *CityCiph, 
	                       U08 *Sectors, 
	                       U08 nSector,
						   U08 *kbuf )
{
	U32 rcode,i,rx_size;
	U08 buf[40],rx_buf[48];

	rcode = M1Card_Hook_GetKey(	CityCode, 		 
								Snr, 
								Csn, 
								MacCode, 
								CityCiph, 
								Sectors, 
								nSector,
								kbuf );
	if( rcode == 0x9000 )
	{ return rcode; }

	buf[0] = 0x80;	//CLA
	buf[1] = 0xFC;	//INS
	buf[2] = 0x00;	//P1 MAC密钥索引号
	buf[3] = 0x01;	//P2 Key密钥索引号
	buf[4] = 0x14+nSector;			//Lc

	buf[5] = CityCode[0]; 			//城市代码
	buf[6] = CityCode[1]; 			//城市代码

	for( i = 0; i < 4; i++ )
	{ buf[i+7] = Snr[i]; } 			//卡片序列号

	buf[11] = Csn[0]; 				//发行流水号
	buf[12] = Csn[1]; 

	for( i = 0; i < 4; i++ )
	{ buf[i+13] = MacCode[i]; } 	//验证码

	for( i = 0; i < nSector; i++ )
	{ buf[i+17] = Sectors[i]; } 	//扇区代码

    memcpy( &buf[nSector+17], CityCode,2 );//城市代码 
	memset( &buf[nSector+19], 0xFF, 6 );

	rcode = M1Card_Hook_7816APDU( buf, ( 25+nSector ), rx_buf, &rx_size, 48 );
	if( rcode == 0 )
	{
		if( rx_size == 2 )
		{
			rcode = ( ( rx_buf[0] << 8 ) | rx_buf[1] );
			if( rcode != 0x9000 )
			{ return rcode; }
		}
		if( rx_size != ( ( nSector * 6 ) + 2 ) )
		{ return 13140; }
		memcpy( kbuf, rx_buf, ( rx_size - 2 ) );

		return 0x9000;
	}

	return rcode;
}

U32 BD_M1Card_Hook_GetKey(	U08 *CityCode, 		 
						U08 *Snr, 
						U08 *Csn, 
						U08 *MacCode, 
						U08 *CityCiph, 
						U08 *Sectors, 
						U08 nSector,
						U08 *kbuf )
{
	U32 i;
	U08 p[8];
	U08 indata[8];
	CurCalc_DataCpy( indata, Snr, 4 );
	CurCalc_DataCpy( indata+4, Csn, 2 );
	CurCalc_DataCpy( indata+6, MacCode, 1 );
	for(i=2;i<16;i++)
	{
		indata[7] = i;
		CurCalc_DES_Encrypt( MAINKEY, indata, p );
		CurCalc_DataCpy(M1Key[i],p,6);
		M1Key[i][6] = 1;
	}
	return 0x9000;
}

U32 BD_MiOne_GetPsamKey( U08 *p_CardSN, U08 *buf, U08 *Sectors, U32 secsize )
{	
	U32 i=0,c=0;
	
	U08 CityCode[2];  
	U08 Snr[4];
	U08 Csn[2];
	U08 MacCode[4];
	U08 kbuf[48];
	U16 rcode;
	U08 CityCiph[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};	//分散因子

	CityCode[0] = buf[0];										//城市代码
	CityCode[1] = buf[1];
	
	Csn[0] = buf[6]; 											//发行流水号低2字节
	Csn[1] = buf[7];
	
	MacCode[0] = buf[8];   										//卡认证码
	MacCode[1] = buf[9];
	MacCode[2] = buf[10];
	MacCode[3] = buf[11];
	
	CurCalc_DataCpy( Snr, p_CardSN, 4 );           				//卡唯一号,是前半字节还是后半字节
	
	rcode = BD_M1Card_Hook_GetKey( CityCode,
										Snr,
										Csn,
										MacCode,
										CityCiph,
										&Sectors[i],
										c,
										kbuf );					//
	if( rcode != 0x9000 )                                   // 密钥计算成功
	{ return rcode; }
		
	return 0; 	
}
//key
U32 MiOne_GetPsamKey( U08 *p_CardSN, U08 *buf )
{
	U08 CityCode[2];  
	U08 Snr[4];
	U08 Csn[2];
	U08 MacCode[4];
	U08 kbuf[48];
	U16 rcode;
	U08 CityCiph[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};	//分散因子
	U08 Sectors[] = { 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A };  //要计算的扇区号    9个扇区	


	CityCode[0] = buf[0];										//城市代码
	CityCode[1] = buf[1];
	
	Csn[0] = buf[6]; 											//发行流水号低2字节
	Csn[1] = buf[7];
	
	MacCode[0] = buf[8];   										//卡认证码
	MacCode[1] = buf[9];
	MacCode[2] = buf[10];
	MacCode[3] = buf[11];
	
	memcpy( Snr, p_CardSN, 4 );           				//卡唯一号,是前半字节还是后半字节
	
	rcode = APP_M1Card_Hook_GetKey( CityCode,
		                           	Snr,
		                     		Csn,
		                           	MacCode,
									CityCiph,
									Sectors,
									6,
									kbuf );					
	if( rcode == 0x9000 )                                   	// 密钥计算成功
	{
		memcpy( &M1Key[Sectors[0]][0], kbuf,    6 );   // 2
		memcpy( &M1Key[Sectors[1]][0],	kbuf+6,  6 );   // 3
		memcpy( &M1Key[Sectors[2]][0], kbuf+12, 6 );   // 4
		memcpy( &M1Key[Sectors[3]][0], kbuf+18, 6 );   // 5
		memcpy( &M1Key[Sectors[4]][0], kbuf+24, 6 );   // 6
		memcpy( &M1Key[Sectors[5]][0], kbuf+30, 6 );   // 7   
		
		rcode = APP_M1Card_Hook_GetKey( CityCode,
			                           	Snr,
			                     		Csn,
			                           	MacCode,
										CityCiph,
										(Sectors+6),
										3,
										kbuf );					//9
		if( rcode == 0x9000 )                                   // 密钥计算成功
		{
			memcpy( &M1Key[Sectors[6]][0], kbuf, 6 );	//8
			memcpy( &M1Key[Sectors[7]][0], kbuf+6, 6 );	//9
			memcpy( &M1Key[Sectors[8]][0],	kbuf+12, 6 );//10
			return 0; 	
		} 
	}

	return rcode;
}

U32 
AH_M1Card_ReadAllData_BD( U08 *p_CardSN, U08 *buf, U32 *succ_cout )
{
	U32 rcode,cout,i;
	U08 sector;
	U08 block;
	U08 buf1[16];
	//U08 KEY[16];
	
	//memcpy(KEY,"\x01\xF6\x98\x50\xE4\x8A\x4C\x63",8);

	(*succ_cout) = 0;
	
	rcode = ICC_MiOne_GetPhySn(p_CardSN);//需要先调用此函数获取物理号
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }
	//CurCalc_DES_Decrypt
	//CurCalc_3DES_Encrypt
	CurCalc_DataCpy( gM1CardSN, p_CardSN, 6 );
//===============>>第0区
	M1Key[0][0] = 0xA0;
	M1Key[0][1] = 0xA1;
	M1Key[0][2] = 0xA2;
	M1Key[0][3] = 0xA3;
	M1Key[0][4] = 0xA4;
	M1Key[0][5] = 0xA5;
	sector = 0;	
	block = ( sector * 4 );		
										
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST,  (block+1), buf1, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }	
	cout = 0;
	CurCalc_DataCpy( &buf[cout], buf1, 16 );
	
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, (block+2), buf1, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }											  
	cout += 16;
	CurCalc_DataCpy( &buf[cout], buf1, 16 );

//===============>>第一区 读取发行区
	(*succ_cout)++;
 	CurCalc_DataCpy( &M1Key[1][0], gM1CardSN, 4 );				
	CurCalc_DataCpy( &M1Key[1][4], gM1CardSN, 2 ); 
	M1Key[1][4] = ~gM1CardSN[0];
	M1Key[1][5] = ~gM1CardSN[1];
	M1Key[1][6] = 1;	
	
	sector = 1;	
	block = ( sector * 4 );		
										
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, 	 (block+0), buf1, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }	
	for( rcode = 0; rcode < 16; rcode++ )
	{ gM1_Publish_00[rcode] = buf1[rcode]; }//发行区
	cout = 32;
	CurCalc_DataCpy( &buf[cout], buf1, 16 );

	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, (block+1), buf1, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }
	cout += 16;
	CurCalc_DataCpy( &buf[cout], buf1, 16 );

	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, (block+2), buf1, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }
	cout += 16;
	CurCalc_DataCpy( &buf[cout], buf1, 16 );

	(*succ_cout)++;
//===============>>KEY计算
	PsamStat = 1;
	if( PsamStat != 0 )
	{
		rcode = BD_MiOne_GetPsamKey( gM1CardSN, gM1_Publish_00, 0, cout );
		if( rcode != 0 )
		{ DEF_CZ_MiOneCard_Debug; return rcode; }
	}
						
//===============>>第2区---第15区
	cout = 64;
	for( i = 0; i < 14; i++ )
	{
		sector = 2+i;	
		block = ( sector * 4 );		

		rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST,    (block+0), buf1, &M1Key[sector][0] );
		if( rcode != 0 )
		{ DEF_CZ_MiOneCard_Debug; return rcode; }	
		cout += 16;
		CurCalc_DataCpy( &buf[cout], buf1, 16 );
		
		rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, (block+1), buf1, &M1Key[sector][0] );
		if( rcode != 0 )
		{ DEF_CZ_MiOneCard_Debug; return rcode; }											  
		cout += 16;
		CurCalc_DataCpy( &buf[cout], buf1, 16 );
							
		rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, (block+2), buf1, &M1Key[sector][0] );
		if( rcode != 0 )
		{ DEF_CZ_MiOneCard_Debug; return rcode; }
		cout += 16;
		CurCalc_DataCpy( &buf[cout], buf1, 16 );
		(*succ_cout)++;			
	}
	return 0;
}

U32 AH_M1Card_ReadAllData_20( U08 *p_CardSN, U08 *buf, U32 *succ_cout )
{
	U32 rcode,cout,i;
	U08 sector;
	U08 block;
	U08 buf1[16];

	(*succ_cout) = 0;
	rcode = ICF_SelectSFI( "\xDF\x01", Gich_Sam );
	if( rcode != 0x9000 )
	{ DEF_CZ_MiOneCard_Debug; }
	rcode = ICC_MiOne_GetPhySn(p_CardSN);//需要先调用此函数获取物理号
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }
	//CurCalc_DES_Decrypt
	//CurCalc_3DES_Encrypt
	CurCalc_DataCpy( gM1CardSN, p_CardSN, 6 );
//===============>>第0区
	M1Key[0][0] = 0xA0;
	M1Key[0][1] = 0xA1;
	M1Key[0][2] = 0xA2;
	M1Key[0][3] = 0xA3;
	M1Key[0][4] = 0xA4;
	M1Key[0][5] = 0xA5;
	sector = 0;	
	block = ( sector * 4 );		
										
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST,    (block+1), buf1, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }	
	cout = 0;
	CurCalc_DataCpy( &buf[cout], buf1, 16 );
	
	rcode = APP_M1Card_Hook_BlkRead( NO_REQUST_AUTH, (block+2), buf1, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }											  
	cout += 16;
	CurCalc_DataCpy( &buf[cout], buf1, 16 );

//===============>>第一区 读取发行区
	(*succ_cout)++;
 	CurCalc_DataCpy( &M1Key[1][0], gM1CardSN, 4 );				
	CurCalc_DataCpy( &M1Key[1][4], gM1CardSN, 2 ); 
		
	sector = 1;	
	block = ( sector * 4 );		
										
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, 	 (block+0), buf1, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }	
	cout = 32;
	CurCalc_DataCpy( &buf[cout], buf1, 16 );

	rcode = APP_M1Card_Hook_BlkRead( NO_REQUST_AUTH, (block+1), buf1, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }
	cout += 16;
	CurCalc_DataCpy( &buf[cout], buf1, 16 );

	rcode = APP_M1Card_Hook_BlkRead( NO_REQUST_AUTH, (block+2), buf1, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }
	cout += 16;
	CurCalc_DataCpy( &buf[cout], buf1, 16 );

	(*succ_cout)++;
//===============>>KEY计算
	PsamStat = 1;
	if( PsamStat != 0 )
	{
		rcode = MiOne_GetPsamKey( gM1CardSN, &buf[32] ); 
		if( rcode != 0 )
		{ DEF_CZ_MiOneCard_Debug; return rcode; }		
	}
						
//===============>>第2区---第15区
	cout = 64;
	for( i = 0; i < 14; i++ )
	{
		sector = 2+i;	
		block = ( sector * 4 );		

		rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST,    (block+0), buf1, &M1Key[sector][0] );
		if( rcode != 0 )
		{ DEF_CZ_MiOneCard_Debug; memset(buf1,' ',16); }	
		cout += 16;
		CurCalc_DataCpy( &buf[cout], buf1, 16 );
		
		rcode = APP_M1Card_Hook_BlkRead( NO_REQUST_AUTH, (block+1), buf1, &M1Key[sector][0] );
		if( rcode != 0 )
		{ DEF_CZ_MiOneCard_Debug; memset(buf1,'*',16); }											  
		cout += 16;
		CurCalc_DataCpy( &buf[cout], buf1, 16 );
							
		rcode = APP_M1Card_Hook_BlkRead( NO_REQUST_AUTH, (block+2), buf1, &M1Key[sector][0] );
		if( rcode != 0 )
		{ DEF_CZ_MiOneCard_Debug; memset(buf1,'*',16); }
		cout += 16;
		CurCalc_DataCpy( &buf[cout], buf1, 16 );
		(*succ_cout)++;			
	}

	return 0;
}
void NC_BusCard_DebugOutput( U08* buf)
{ 
	printf("%s",(char*)buf);
}
void AH_M1Card_PrintAllData( void )
{
	U32 rcode,i,cout;
	U08 s,rn,pn;	//扇区号，区内号，物理号
	U08 buf[200];
	U08 rbuf[1024];
	U32 succcout;

	memset(buf,0,200);
	memset(rbuf,0,1024);

	//rcode = AH_M1Card_ReadAllData_20( gM1CardSN, rbuf, &succcout );
	rcode = AH_M1Card_ReadAllData_BD( gM1CardSN, rbuf, &succcout );
	if( rcode != 0 )
	{
		if( succcout == 0 )
		{
			sprintf( (char*)buf, "I-- read failed! er=%d\r\n", rcode );
			NC_BusCard_DebugOutput( buf );
			return ;
		}
	}
	NC_BusCard_DebugOutput( buf );

	sprintf( (char*)buf, "SH NI WU--0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  \r\n" );NC_BusCard_DebugOutput( buf );
	sprintf( (char*)buf, "|  |  |   |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  \r\n" );NC_BusCard_DebugOutput( buf );

	i = 0;
	s = i; rn = 1; pn = (i*4)+1; cout = 0;
	sprintf( (char*)buf, "%02d %02d %02d--%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", s, rn, pn,
	rbuf[cout+0x00],rbuf[cout+0x01],rbuf[cout+0x02],rbuf[cout+0x03],rbuf[cout+0x04],rbuf[cout+0x05],rbuf[cout+0x06],rbuf[cout+0x07],rbuf[cout+0x08],rbuf[cout+0x09],rbuf[cout+0x0A],rbuf[cout+0x0B],rbuf[cout+0x0C],rbuf[cout+0x0D],rbuf[cout+0x0E],rbuf[cout+0x0F]);
	NC_BusCard_DebugOutput( buf );

	s = i; rn = 2; pn = (i*4)+2; cout += 16;
	sprintf( (char*)buf, "%02d %02d %02d--%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", s, rn, pn,
	rbuf[cout+0x00],rbuf[cout+0x01],rbuf[cout+0x02],rbuf[cout+0x03],rbuf[cout+0x04],rbuf[cout+0x05],rbuf[cout+0x06],rbuf[cout+0x07],rbuf[cout+0x08],rbuf[cout+0x09],rbuf[cout+0x0A],rbuf[cout+0x0B],rbuf[cout+0x0C],rbuf[cout+0x0D],rbuf[cout+0x0E],rbuf[cout+0x0F]);
	NC_BusCard_DebugOutput( buf );

	NC_BusCard_DebugOutput( (U08*)"\r\n" );

	for( i = 1; i < succcout; i++ )
	{
		s = i; rn = 0; pn = (i*4)+0; cout += 16;
		sprintf( (char*)buf, "%02d %02d %02d--%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", s, rn, pn,
		rbuf[cout+0x00],rbuf[cout+0x01],rbuf[cout+0x02],rbuf[cout+0x03],rbuf[cout+0x04],rbuf[cout+0x05],rbuf[cout+0x06],rbuf[cout+0x07],rbuf[cout+0x08],rbuf[cout+0x09],rbuf[cout+0x0A],rbuf[cout+0x0B],rbuf[cout+0x0C],rbuf[cout+0x0D],rbuf[cout+0x0E],rbuf[cout+0x0F]);
		NC_BusCard_DebugOutput( buf );
	
		s = i; rn = 1; pn = (i*4)+1; cout += 16;
		sprintf( (char*)buf, "%02d %02d %02d--%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", s, rn, pn,
		rbuf[cout+0x00],rbuf[cout+0x01],rbuf[cout+0x02],rbuf[cout+0x03],rbuf[cout+0x04],rbuf[cout+0x05],rbuf[cout+0x06],rbuf[cout+0x07],rbuf[cout+0x08],rbuf[cout+0x09],rbuf[cout+0x0A],rbuf[cout+0x0B],rbuf[cout+0x0C],rbuf[cout+0x0D],rbuf[cout+0x0E],rbuf[cout+0x0F]);
		NC_BusCard_DebugOutput( buf );

		s = i; rn = 2; pn = (i*4)+2; cout += 16;
		sprintf( (char*)buf, "%02d %02d %02d--%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", s, rn, pn,
		rbuf[cout+0x00],rbuf[cout+0x01],rbuf[cout+0x02],rbuf[cout+0x03],rbuf[cout+0x04],rbuf[cout+0x05],rbuf[cout+0x06],rbuf[cout+0x07],rbuf[cout+0x08],rbuf[cout+0x09],rbuf[cout+0x0A],rbuf[cout+0x0B],rbuf[cout+0x0C],rbuf[cout+0x0D],rbuf[cout+0x0E],rbuf[cout+0x0F]);
		NC_BusCard_DebugOutput( buf );
		NC_BusCard_DebugOutput( (U08*)"\r\n" );
	}

}

U32 AH_M1Card_ReadPublish( U08 *p_CardSN, U08 *buf, U08 ver )
{
	U32 rcode;
	U08 sector;
	U08 block;

	CurCalc_DataCpy( gM1CardSN, p_CardSN, 6 );
//	CurCalc_DataCpy( gM1CardSN, "\xFF\xFF\xFF\xFF\xFF\xFF", 6 );
//===============>>读取发行区	
	CurCalc_DataCpy( &M1Key[1][0], gM1CardSN, 4 );				
	CurCalc_DataCpy( &M1Key[1][4], gM1CardSN, 2 ); 
	M1Key[1][4] = ~gM1CardSN[0];
	M1Key[1][5] = ~gM1CardSN[1];
	M1Key[1][6] = 1;				
	sector = M1_SECTOR_01;	
	block = ( sector * 4 );		
										
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, 	 (block+0), buf,    &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug;return rcode; }	
//	if( ( ( ver & 0x01 ) != 0 ) && ( CheckXOR( buf ) != 0 ) ) 			//校验
//	{ return 13100; }
	for( rcode = 0; rcode < 16; rcode++ )
	{ gM1_Publish_00[rcode] = buf[rcode]; }//发行区

	rcode = APP_M1Card_Hook_BlkRead( NO_REQUST_AUTH, (block+1), buf+16, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug;return rcode; }
//	if( ( ( ver & 0x02 ) != 0 ) && ( CheckXOR( buf + 16 ) != 0 ) )		//校验
//	{ return 13100; }

	rcode = APP_M1Card_Hook_BlkRead( NO_REQUST_AUTH, (block+2), buf+32, &M1Key[sector][0] );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug;return rcode; }
//	if( ( ( ver & 0x04 ) != 0 ) && ( CheckXOR( buf + 32 ) != 0 ) )		//校验
//	{ return 13100; }
//===============>>KEY计算
	rcode = BD_MiOne_GetPsamKey( gM1CardSN, gM1_Publish_00, 0, 0 );
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug; return rcode; }
	
	return 0;	
}

U32 AH_M1Card_ReadCommInfo( U08 *buf )
{
	U32 rcode,i;
	U08 sector;
	U08 block,buf1[16];

//===============>>	
	sector = M1_SECTOR_06;	
	block = ( sector * 4 );	
			
///////////主区与备份区						
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, ( block + 0 ), buf, &M1Key[sector][0] );		  								
	if( rcode != 0 )							 			//读取主区
	{ DEF_CZ_MiOneCard_Debug;return rcode; }  
	if( CheckXOR( buf ) )									//主区校验不过
	{
		rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, ( block + 1 ), buf, &M1Key[sector][0] );
		if( rcode != 0 )							 		//读取备份区
		{ DEF_CZ_MiOneCard_Debug;return rcode; }  				
		if( CheckXOR( buf ) )								//备份区以校验不过
		{ DEF_CZ_MiOneCard_Debug;return 13100; }
		if( CurCalc_DataCmp( gM1_ComBuf16Byte, buf, 3 ) == 0 )
		{
			if( CurCalc_DataCmp( &gM1_ComBuf16Byte[4], &buf[4], 11 ) == 0 )
			{												//缓存除进程标记外，其它字段都是一样的,校验字段不判断
				CurCalc_DataCpy( buf, gM1_ComBuf16Byte, 16 );
			}												//缓存数据恢复主区
		}
		APP_M1Card_Hook_BlkWrite( OLNY_REQUST, ( block + 0 ), buf, &M1Key[sector][0] );
	}														//将备份区恢复主区
	else													//主区校验过了，直接将备份区写一下
	{		
		rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, ( block + 1 ), buf1, &M1Key[sector][0] );		  								
		if( rcode != 0 )							 		//读取备份区
		{ DEF_CZ_MiOneCard_Debug;return rcode; }  
		for( i = 0; i < 16; i++ )							//两者不一样才进行写操作 20120904
		{
			if( buf[i] != buf1[i] )	
			{ 
				rcode = APP_M1Card_Hook_BlkWrite( OLNY_REQUST, ( block + 1 ), buf, &M1Key[sector][0] );
				if( rcode != 0 )							 //备份区
				{ DEF_CZ_MiOneCard_Debug;return rcode; }  	
				break; 
			}
		}	
     }
									 
///////////第三块
	
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, ( block + 2 ), (buf+16), &M1Key[sector][0] );
	if( rcode != 0 )							 
	{ DEF_CZ_MiOneCard_Debug;return rcode; }  

	return 0;
}

U32 AH_M1Card_WriteCommInfo( U08 *buf )
{	 
	U32 rcode;
	U08 sector;
	U08 block;

//===============>>	
	sector = M1_SECTOR_06;	
	block = ( sector * 4 );	
			
///////////主区与备份区			
	buf[15] = 0;
	buf[15] = CheckXOR( buf );	
	rcode = APP_M1Card_Hook_BlkWrite( OLNY_REQUST, 	  ( block + 0 ), buf, &M1Key[sector][0] );
	if( rcode != 0 )							 			//主区
	{ DEF_CZ_MiOneCard_Debug;return rcode; }  		
	rcode = APP_M1Card_Hook_BlkWrite( OLNY_REQUST, ( block + 1 ), buf, &M1Key[sector][0] );
	if( rcode != 0 )							 			//备份区
	{ DEF_CZ_MiOneCard_Debug;return rcode; }  			  								

	return 0;
}

U32 AH_M1Card_WriteRecFile( U08 *p_CardSN, U08 recno, U08 *recbuf )
{
	U32 rcode;
	U08 sector;
	U08 block;
	//保定的老卡记录指针可变态，序号是从1，2，3，4，5，6，7，8，0对应记录扇区3,4,5
	if( recno > 8 )			//记录指针zj20101102
	{ recno = 0; }
	recno++;
	if( recno == 9)
	{
		sector = M1_SECTOR_05;
		recno = 2;
	}
	else
	{
	//===============>>	
		if( recno < 4 )
		{ 
			sector = M1_SECTOR_03; 
			recno = ( ( recno - 1 ) % 3 );
		}
		else if( recno < 7 )
		{ 
			sector = M1_SECTOR_04;
			recno -= 3;
			recno = ( ( recno - 1 ) % 3 ); 
		}
		else
		{ 
			sector = M1_SECTOR_05;
			recno -= 6;
			recno = ( ( recno - 1 ) % 3 );  
		}
	}
		
	block = ( sector * 4 );	

	rcode = APP_M1Card_Hook_BlkWrite( OLNY_REQUST, ( block + recno ), recbuf, &M1Key[sector][0] );
	if( rcode != 0 )							 			//读取主区
	{ DEF_CZ_MiOneCard_Debug;return rcode; }  

	return 0;
}

U32 AH_M1Card_ReadRecFile( U08 *p_CardSN, U08 recno, U08 *recbuf )
{
	U32 rcode;
	U08 sector;
	U08 block;

	if( recno > 8 )
	{ return 13150; }
	
	if( recno == 0 )
	{
		sector = M1_SECTOR_05;
		recno = 2;  
	}
	else
	{
	//===============>>	
		if( recno < 4 )
		{ 
			sector = M1_SECTOR_03; 
			recno = ( ( recno - 1 ) % 3 );
		}
		else if( recno < 7 )
		{ 
			sector = M1_SECTOR_04;
			recno -= 3;
			recno = ( ( recno - 1 ) % 3 ); 
		}
		else
		{ 
			sector = M1_SECTOR_05;
			recno -= 6;
			recno = ( ( recno - 1 ) % 3 );  
		}
	}
		
	block = ( sector * 4 );	

	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, ( block + recno ), recbuf, &M1Key[sector][0] );
	if( rcode != 0 )							 			//读取主区
	{ return rcode; }  

	return 0;
}

U32 WriteCardCoutWallet( U32 money, U32 *newmoney, U08 *combuf, U08 *recbuf, U32 sect )
{	
	U32 rcode;
	U08 sector;
	U08 block;//,rec_rp;
	U08 buf1[16],buf2[16];
	U32 wallet;
	U16 dc;

//===============>>(01)公共信息主区, 写进程标记，记录指针，钱包累计交易计数
	sector = M1_SECTOR_06;	
	block = ( sector * 4 );	

	//combuf[4] = 1;											//进程标识	
	if( sect == M1_SECTOR_02 )							  	//电子钱包
	{ combuf[4] = 1; }										//进程标识	
	else if( sect == M1_SECTOR_07 )					 			//次卡	  M1_SECTOR_08
	{ combuf[4] = 3; }										//进程标识
	else if( sect == M1_SECTOR_08 )					 			//次卡	  M1_SECTOR_08
	{ combuf[4] = 5; }										//进程标识	
	else 		   											//月票
	{ DEF_CZ_MiOneCard_Debug;return 13201; }
	
	combuf[15] = 0;
	combuf[15] = CheckXOR( combuf );	
	if( APP_M1Card_Hook_BlkWrite( OLNY_REQUST, ( block + 0 ), combuf, &M1Key[sector][0] ) != 0 )
	{ return 1; }			  								//主区
//===============>>(02)写卡上交易记录
	rcode = AH_M1Card_WriteRecFile( 0, (combuf[1]), recbuf );
	if( rcode != 0 )										//写记录 zj20101102
	{ DEF_CZ_MiOneCard_Debug;return rcode; }						 			
//===============>>(03)读取钱包 余额判断，减钱
	sector = sect;	
	block = ( sector * 4 );	

	if( sect == M1_SECTOR_02 )								//钱包
	{ wallet = gWalletM1[0]; }
	else if(( sect == M1_SECTOR_07 )||( sect == M1_SECTOR_08 ))		//次卡	
	{ wallet = gWalletM1[2]; }
	else													//月票	wallet = LY_gWalletM1[1]
	{ return 1; }
	if( money > wallet ) 									//
	{ return 13110; }										//
//=======>>钱包减钱	主区
	buf1[0] = ( money >>  0 );								//消费金额
	buf1[1] = ( money >>  8 );
	buf1[2] = ( money >> 16 );
	buf1[3] = ( money >> 24 );
	buf1[4] = ~buf1[0];
	buf1[5] = ~buf1[1];
	buf1[6] = ~buf1[2];
	buf1[7] = ~buf1[3];
	CurCalc_DataCpy( &buf1[8], buf1, 4 ); 					//更新主区

	CurCalc_DataCpy( buf2, buf1, 16 );						//备份区

	rcode = APP_M1Card_Hook_AuthBlkKey( PICC_KEYA, ( block + 3 ), &M1Key[sector][0] );
	if( rcode != 0 )										//校验密码
	{ DEF_CZ_MiOneCard_Debug; return rcode; }						   			
	rcode = APP_M1Card_Hook_Value( PICC_SUB, ( block + 1 ), buf1, ( block + 1 ) );
	if( rcode != 0 )										//写主区
	{ DEF_CZ_MiOneCard_Debug; return rcode; }  	
////=======>>写进程标记  结束
	CurCalc_DataCpy( gM1_ComBuf16Byte, combuf, 16 );		//缓存数据

	sector = M1_SECTOR_06;	
	block = ( sector * 4 );	

	combuf[1]++; 											//
	if( combuf[1] > 8 )
	{ combuf[1] = 0; }

	if( sect == M1_SECTOR_02 )							  	//电子钱包
	{ 
		dc = ( ( combuf[2] << 8 ) | combuf[3] );
		dc++;												//钱包累计交易计数
		combuf[2] = ( dc >> 8 );
		combuf[3] = dc;										//zj20101102
	
		combuf[ 4] = 2;										//进程标记		 
	}									 
	else if( sect == M1_SECTOR_07 )					 			//次卡 M1_SECTOR_08
	{ 
		dc = ( ( combuf[5] << 8 ) | combuf[6] );
		dc++;												//月票累计交易计数
		combuf[5] = ( dc >> 8 );
		combuf[6] = dc;
		
		combuf[4] = 6;										//进程标记	
	}
	else 		   											//月票
	{ 
		dc = ( ( combuf[5] << 8 ) | combuf[6] );
		dc++;												//月票累计交易计数
		combuf[5] = ( dc >> 8 );
		combuf[6] = dc;
	
		combuf[4] = 8;										//进程标记	
	}	

	combuf[15] = 0;
	combuf[15] = CheckXOR( combuf );	
	rcode = APP_M1Card_Hook_BlkWrite( OLNY_REQUST, ( block + 0 ), combuf, &M1Key[sector][0] );
	if( rcode != 0 )										//主区
	{ return 13200; }	  								
	CurCalc_DataSet( gM1_ComBuf16Byte, 0x00, 16 );			//已经用到不此值了清0 zj20140219
////===============>>(04)钱包 备份区

	sector = M1_SECTOR_02;	
	block = ( sector * 4 );	
	rcode = APP_M1Card_Hook_AuthBlkKey( PICC_KEYA, ( block + 3 ), &M1Key[sector][0] );						
	if( rcode != 0 )										//校验密码
	{ goto RET; } 
	rcode = APP_M1Card_Hook_Value( PICC_RESTORE, ( block + 1 ), buf1, ( block + 2 ) );
	if( rcode != 0 )										//主到备
	{ goto RET; } 
													    	
//===============>>(05)公共信息备份区, 写进程标记，记录指针，钱包累计交易计数
	sector = M1_SECTOR_06;	
	block = ( sector * 4 );	

	combuf[15] = 0;
	combuf[15] = CheckXOR( combuf );						//公共信息区备份区	
	APP_M1Card_Hook_BlkWrite( OLNY_REQUST, ( block + 1 ), combuf, &M1Key[sector][0] );
	RET:
	*newmoney = ( wallet - money );							//当前余额

	return 0;
}

U32 ReadCardWalletErrPro( U32 sector, U08 *combuf )
{
	U32 rcode;
	U08 block;
	U08 buf1[16],buf2[16];

//===============>>读取公共信息区	

//===============>>读取钱包
	//ctor = M1_SECTOR_08;	
	block = ( sector * 4 );	
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, 	 ( block + 1 ), buf1, &M1Key[sector][0] );								
	if( rcode != 0 )										//读取主区
	{ DEF_CZ_MiOneCard_Debug;return rcode; }
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, ( block + 2 ), buf2, &M1Key[sector][0] );
	if( rcode != 0 )										//读取备份区
	{ DEF_CZ_MiOneCard_Debug;return rcode; }				

//===============>>钱包校验
	if( CheckWallet( buf1 ) != 0 )							//主块校验
	{
		if( CheckWallet( buf2 ) != 0 ) 						//两块都校验不过
		{ DEF_CZ_MiOneCard_Debug;return 13120; } 
		
		rcode = APP_M1Card_Hook_Value( PICC_RESTORE, ( block + 2 ), buf2, ( block + 1 ) );
		if( rcode != 0 )									//备到主
		{ DEF_CZ_MiOneCard_Debug;return rcode; }									    
		CurCalc_DataCpy( buf1, buf2, 16 );
	}
	else if( CheckWallet( buf2 ) != 0 )						//备份块校验
	{
		rcode = APP_M1Card_Hook_Value( PICC_RESTORE, ( block + 1 ), buf1, ( block + 2 ) );
		if( rcode != 0 )									//主到备
		{ DEF_CZ_MiOneCard_Debug;return rcode; }
		CurCalc_DataCpy( buf2, buf1, 16 );
	}

//===============>>进程标记判断
	if( combuf[4] % 2 )										//1 钱包扣款开始			备-->主
	{
		if( CurCalc_DataCmp( buf1, buf2, 16 ) != 0 )		//主要为了提高速度
		{
			rcode = APP_M1Card_Hook_Value( PICC_RESTORE, ( block + 2 ), buf2, ( block + 1 ) );
			if( rcode != 0 )								//备到主
			{ DEF_CZ_MiOneCard_Debug;return rcode; }						
		}
		//更改进程标记	
		combuf[4] += 1;
		rcode = AH_M1Card_WriteCommInfo( combuf );
		if( rcode != 0 )									//异常处理完成	
		{ DEF_CZ_MiOneCard_Debug;return rcode; }
	}
	else 													//2 钱包扣款完成			主-->备
	{
		if( CurCalc_DataCmp( buf1, buf2, 16 ) != 0 )		//主要为了提高速度
		{
			rcode = APP_M1Card_Hook_Value( PICC_RESTORE, ( block + 1 ), buf1, ( block + 2 ) );
			if( rcode != 0 )								//主到备
			{ DEF_CZ_MiOneCard_Debug;return rcode; }		
		}
	}
	return 0;
}

U32 AH_M1Card_ReadCardWallet( U32 *wallet, U08 *combuf )
{
	U32 rcode;
	U08 sector;
	U08 block;
	U08 buf1[16],buf2[16];

	printf("AH_M1Card_ReadCardWallet:\n");

//===============>>读取公共信息区	
	rcode = AH_M1Card_ReadCommInfo( combuf );		//读取公共信息区
	if( rcode != 0 )
	{ DEF_CZ_MiOneCard_Debug;return rcode; }
//===============>>进程标记判断
	if( combuf[4] > 2 )										//其它钱包
	{
		if( combuf[4] % 2 )									//其它钱包交易开始
		 {
			if( combuf[4] == 7 )   							//月票钱包开始
			{
			    DEF_CZ_MiOneCard_Debug; 
			}
			else if( combuf[4] == 3 )		 				//次卡钱包开始
			{
				rcode = ReadCardWalletErrPro( M1_SECTOR_07, combuf );
				if( rcode != 0 )
				{ DEF_CZ_MiOneCard_Debug; return rcode; }
			}
			else if( combuf[4] == 5 )
			{
			    rcode = ReadCardWalletErrPro( M1_SECTOR_08, combuf );
				if( rcode != 0 )
				{ DEF_CZ_MiOneCard_Debug; return rcode; }
			}
			else
			{ DEF_CZ_MiOneCard_Debug; }
		}
	}
//===============>>读取钱包
	sector = M1_SECTOR_02;	
	block = ( sector * 4 );	
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, ( block + 1 ), buf1, &M1Key[sector][0] );								
	if( rcode != 0 )										//读取主区
	{ DEF_CZ_MiOneCard_Debug;return rcode; }
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, ( block + 2 ), buf2, &M1Key[sector][0] );
	if( rcode != 0 )										//读取备份区
	{ DEF_CZ_MiOneCard_Debug;return rcode; }				

//===============>>钱包校验
	if( CheckWallet( buf1 ) != 0 )							//主块校验
	{
		if( CheckWallet( buf2 ) != 0 ) 						//两块都校验不过
		{ DEF_CZ_MiOneCard_Debug;return 13120; } 
		
		rcode = APP_M1Card_Hook_Value( PICC_RESTORE, ( block + 2 ), buf2, ( block + 1 ) );
		if( rcode != 0 )									//备到主
		{ DEF_CZ_MiOneCard_Debug;return rcode; }									    
		CurCalc_DataCpy( buf1, buf2, 16 );
	}
	else if( CheckWallet( buf2 ) != 0 )						//备份块校验
	{
		rcode = APP_M1Card_Hook_Value( PICC_RESTORE, ( block + 1 ), buf1, ( block + 2 ) );
		if( rcode != 0 )									//主到备
		{ DEF_CZ_MiOneCard_Debug;return rcode; }
		CurCalc_DataCpy( buf2, buf1, 16 );
	}
//===============>>进程标记判断
	if( combuf[4] <= 2)
	{
		if( combuf[4] % 2 )										//1 钱包扣款开始			备-->主
		{
			if( CurCalc_DataCmp( buf1, buf2, 16 ) != 0 )		//主要为了提高速度
			{
				//备到主
				rcode = APP_M1Card_Hook_Value( PICC_RESTORE, ( block + 2 ), buf2, ( block + 1 ) );
				if( rcode != 0 )							
				{ DEF_CZ_MiOneCard_Debug;return rcode; }

				CurCalc_DataCpy( buf1, buf2, 16 );	
			}
			//更改进程标记	
			combuf[4] += 1;
			AH_M1Card_WriteCommInfo( combuf );		//异常处理完成
			if( rcode != 0 )									//异常处理完成	
		    { return rcode; }	
		}
		else 													//2 钱包扣款完成			主-->备
		{
			if( CurCalc_DataCmp( buf1, buf2, 16 ) != 0 )		//主要为了提高速度
			{
				 //主到备
				rcode = APP_M1Card_Hook_Value( PICC_RESTORE, ( block + 1 ), buf1, ( block + 2 ) );
				if( rcode != 0 )							
				{ DEF_CZ_MiOneCard_Debug;return rcode; }
				CurCalc_DataCpy( buf2, buf1, 16 );
			}	
		}
	}

	wallet[0] = ( 	( buf1[0] <<  0 ) |						//卡内余额 
	         		( buf1[1] <<  8 ) | 
			 		( buf1[2] << 16 ) | 
			 		( buf1[3] << 24 ) );
    gWalletM1[0] = wallet[0];

    printf("ok!\n");
	return 0;
}

U32 AH_M1Card_WriteCardWallet( U32 money, U32 *newmoney, U08 *combuf, U08 *recbuf )
{
	U32 sect;
	sect = M1_SECTOR_02;
	return WriteCardCoutWallet(money,newmoney,combuf,recbuf,sect);
}

U32 AH_M1Card_WriteCardNumWallet( U32 money, U32 *newmoney, U08 *combuf, U08 *recbuf )
{
	U32 sect;
	sect = M1_SECTOR_07;
	return ( WriteCardCoutWallet( money, newmoney, combuf, recbuf, sect ) ); 
}

U32 AH_M1Card_WriteCardState( U08 *p_CardSN, U08 cardstate )
{
	U32 rcode;
	U08 sector;
	U08 block;
	U08 buf[16];

//===============>>	
	sector = M1_SECTOR_06;	
	block = ( sector * 4 );	

//此种方式是主区与备份区分开写的，这样的话进程标记是不会被破坏的
///////////主区	
	rcode = APP_M1Card_Hook_BlkRead( OLNY_REQUST, ( block + 0 ), buf, &M1Key[sector][0] );
	if( rcode != 0 )							 
	{ return rcode; }  
	buf[7]  = cardstate;
	buf[15] = 0;
	buf[15] = CheckXOR( buf );
	rcode = APP_M1Card_Hook_BlkWrite( NO_REQUST_AUTH, ( block + 0 ), buf, &M1Key[sector][0] );
	if( rcode != 0 )							 
	{ return rcode; }  

///////////备份区
	rcode = APP_M1Card_Hook_BlkRead( NO_REQUST_AUTH, ( block + 1 ), buf, &M1Key[sector][0] );
	if( rcode != 0 )							 
	{ return rcode; }  
	buf[7]  = cardstate;
	buf[15] = 0;
	buf[15] = CheckXOR( buf );
	rcode = APP_M1Card_Hook_BlkWrite( NO_REQUST_AUTH, ( block + 1 ), buf, &M1Key[sector][0] );
	if( rcode != 0 )							 
	{ return rcode; }  

	return 0;
}